import wx.dataview as wxdv
from typing import List, Any, Tuple

# string 字符串；datetime 日期；bool 布尔类型复选框

class Field(object):
    '''真正的数据行'''
    def __init__(self, fieldType, *args, **kwargs):
        self.fieldType = fieldType

    def __repr__(self):
        return 'Field: %s-%s' % (self.fieldType, self.alias)

class FieldType(object):
    '''节点构造'''
    def __init__(self, name, *args, **kwargs):
        self.name = name # 字段类型 的 称呼
        self.fields = [] # 字段的集合

    def __repr__(self):
        return 'FieldType: ' + self.name

class ShowModelsModel(wxdv.PyDataViewModel):

    def __init__(self, data: List[FieldType], option_names: List[str]):
        wxdv.PyDataViewModel.__init__(self)
        self.data = data # 获取传递过来的渲染数据
        self.option_names = option_names # 选项名
        self.UseWeakRefs(True) # 数据节点是 弱引用 时启用

    def GetColumnCount(self):
        '''返回数据总的列数'''
        return len(self.option_names) + 2 # 节点名 + 末尾空列

    def GetColumnType(self, col):
        '''设置列的类型'''
        types = []
        for _ in range(len(self.option_names) + 2):
            types.append('string')
        mapper = {i:_ for i,_ in enumerate(types)}
        return mapper[col] # 返回给构造器类型

    def GetChildren(self, parent, children):
        '''获取所有的孩子节点数据'''
        if not parent: # 没有父节点
            for fieldType in self.data: # 遍历节点的数据包
                children.append(self.ObjectToItem(fieldType))
            return len(self.data)

        node = self.ItemToObject(parent) # 有父节点的情况（复杂数据结构）
        if isinstance(node, FieldType): # 父节点类型检测
            for field in node.fields: # 取复杂数据结构的数据区域
                children.append(self.ObjectToItem(field))
            return len(node.fields)
        return 0

    def IsContainer(self, item):
        '''当前节点有子节点则返回 True '''
        
        if not item: # 节点
            return True
            
        node = self.ItemToObject(item)
        if isinstance(node, FieldType): # 数据包
            return True
            
        return False # 数据行

    def GetParent(self, item):
        '''返回该节点的父节点'''
        if not item:
            return wxdv.NullDataViewItem

        node = self.ItemToObject(item)
        if isinstance(node, FieldType):
            return wxdv.NullDataViewItem
        elif isinstance(node, Field):
            for g in self.data:
                if g.name == node.fieldType:
                    return self.ObjectToItem(g)

    def HasValue(self, item, col):
        '''判断是否是有效的数据行（非展开节点）'''
        node = self.ItemToObject(item)
        if isinstance(node, FieldType) and col > 0: # 只在第一列渲染节点数据
            return False
        return True

    def GetValue(self, item, col):
        '''获取某一具体单元格的值，0 表示第一列'''
        node = self.ItemToObject(item) # 获取当前节点对象

        '''
            下面的条件分支存在问题，目前不严重，等严重后进行整改
        '''
        if isinstance(node, FieldType): # 如果是节点，直接返回节点的 name 属性
            return node.name # 节点只需要名称

        elif isinstance(node, Field): # 数据包的行
            data = [node.fieldType, ]
            for col_name in self.option_names:
                data.append(getattr(node, col_name[0]))
            data.append('') # 解决 BUG 列
            mapper = {i:_ for i, _ in enumerate(data)}
            return mapper[col]

        else:
            raise RuntimeError('未知的节点类型')

    def GetRowListValue(self, item):
        '''获取焦点所在行的列表数据集（不包含 首列 和 尾列）'''
        node = self.ItemToObject(item)
        if isinstance(node, FieldType):
            return [] # 节点返回空数据
        return [self.GetValue(item, i) for i in range(self.GetColumnCount())[1:-1]]

    def GetRowDictValue(self, item):
        '''获取焦点所在行的字典数据集
        
            【数据包动态构建，无固定格式】
            col_names：选项键（如：verbose_name ... ）
        '''
        node = self.ItemToObject(item)
        if isinstance(node, FieldType):
            return {}
        row = {}
        for col_name in self.option_names:
            row[col_name[0]] = getattr(node, col_name[0])
        return row

    def GetAttr(self, item, col, attr):
        '''设置节点的属性'''
        node = self.ItemToObject(item)
        if isinstance(node, FieldType):
            attr.SetColour('blue')
            attr.SetBold(True)
            return True
        return False

    def SetValue(self, value, item, col):
        '''第一列不允许改变，即不存在 0 == col 的情况'''
        node = self.ItemToObject(item)
        if isinstance(node, Field):
            # if col == 1:
            #     node.op = value
            # elif col == 2:
            #     node.relate_path = value
            pass
        return True

    def IsRowData(self, item) -> bool:
        """判断当前行是不是数据行
        
            如果是节点行，返回 False
            如果是数据行，返回 True
        """
        node = self.ItemToObject(item)
        if isinstance(node, FieldType):
            return False
        return True
